package cn.xiaolang.function.java_gc;

import cn.xiaolang.common.utils.Monitor;
import lombok.extern.slf4j.Slf4j;

import java.lang.ref.*;
import java.util.concurrent.TimeUnit;

/**
 * 二 对象引用之-弱引用
 * <p>
 * 具有弱引用的对象，不管当前内存空间足够与否，都会回收它的内存。
 * 不过，由于垃圾回收器是一个 优先级很低的线程，因此不一定会很快发现那些只具有弱引用的对象。
 * <p>
 * 弱引用可以和一个引用队列(ReferenceQueue)联合使用，如果弱引用的对象被垃圾回收，
 * JVM就会把这个弱引用加入到与之关联的引用队列中
 * </p>
 *
 * @author fuhw/Dean
 * @date 2020-05-14
 */
@Slf4j
public class WeakReferenceStarted {


    public static void main(String[] args) throws InterruptedException {
        weakReferenceStart();
    }

    private static void weakReferenceStart() throws InterruptedException {

        System.gc();
        TimeUnit.SECONDS.sleep(3);

        Monitor.printlnMemory("1.原可用内存和总内存");
        // 强引用
        byte[] object = new byte[10 * Monitor.MB];
        Monitor.printlnMemory("2.实例化10M的数组后");

        // 建立弱引用
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
        WeakReference<Object> weakReference = new WeakReference<>(object, referenceQueue);
        Monitor.printlnMemory("3.建立弱引用,可以通过get()方法获取到关联对象");
        System.out.println("weakReference : " + weakReference);
        System.out.println("weakReference.get() : " + weakReference.get());
        System.out.println("referenceQueue.poll() : " + referenceQueue.poll());

        // 断开object的强引用
        object = null;
        Monitor.printlnMemory("4.执行object=null;断开强引用后");

        // Notify GC
        System.gc();
        // 休息一段时间等待上面的垃圾回收线程运行完成
        TimeUnit.SECONDS.sleep(3);

        //真实回收object[]对象,由于GC线程优先级低，不一定会很快发现弱引用对象
        Monitor.printlnMemory("5.GC后,真实回收object[]对象<===>");
        System.out.println("weakReference : " + weakReference);
        System.out.println("weakReference.get() : " + weakReference.get());
        System.out.println("referenceQueue.poll() : " + referenceQueue.poll());
    }


}
